#include "ObservateurBase.h"

using namespace std;

ObservateurBase::ObservateurBase(FenetreObservateur *ptrFenetre)
{
    connecte = false;
    this->ptrFenetre = ptrFenetre;
}

ObservateurBase::~ObservateurBase()
{
    fermerSocket("Destruction de observateurBase");
}

bool ObservateurBase::ouvrirSocket(const char *ip, const char *port)
{
    activite = 0;
    this->port = port;
    this->ip = ip;
    info = gethostbyname(this->ip);
    if(info)
    {
        serveur.sin_family = AF_INET;
        serveur.sin_addr.s_addr = htonl(ntohl(* (uint32_t *)info->h_addr));
        serveur.sin_port = htons(atoi(this->port));
        this->sock = socket(PF_INET, SOCK_STREAM, 0);
        if(sock >= 0)
        {
            if(!::connect(this->sock, (struct sockaddr *) &serveur, sizeof(serveur)))
            {
                connecte = true;
                pthread_create(&threadLecture, NULL, thread_attendreMessage, (void *)this);
                return true;
            }
        }
    }
    return false;
}

void ObservateurBase::fermerSocket(const QString &cause)
{
    if(connecte) emit estDeconnecte(cause);
    connecte = false;
    shutdown(sock, 2);
    close(sock);
}

void ObservateurBase::attendreMessage()
{
    ecrireMessage(OBS_LOGIN, ptrFenetre->getLogin());
    int idMessage;
    while(connecte)
    {
        idMessage = lireEntierUnOctet();
        if(idMessage == 0) fermerSocket("Connexion au serveur perdue.");
        else traitementMessage(idMessage);
    }
}

void ObservateurBase::traitementMessage(int idMessage) // renvoie 0 si le message recu mais fin a la connexion avec le serveur.
{
    switch(idMessage)
    {
    case OBS_ERR_LOGIN:
        connecte = false;
        emit estDeconnecte("Login incorrect");
        break;
    case OBS_LISTE:
        {
            emit estConnecte();
            QStringList listeSalles = stringListToQStringList(lireListeChaines());
            emit sallesRecues(listeSalles);
            ptrFenetre->ecrireConsole2("Connecté au lobby");
        }
        break;
    case OBS_ERR_CHOIX:
        //Le choix de de salle est impossible
        ptrFenetre->ecrireConsole2("Impossible d'ouvrir cette salle");
        break;
    case OBS_OK_CHOIX:
        {
            emit connecteasalle();
            ecrireMessage(OBS_ACTIVITES, qStringListToStringList(ptrFenetre->listeAct()));
        }
        break;

    case OBS_OK_CHOIX_SALLE_CREE:
        {
            ecrireMessage(OBS_ACTIVITES, qStringListToStringList(ptrFenetre->listeAct()));

            break;
        }
    case OBS_ACTIVITE_OK:
        {
            QStringList QlisteAct = stringListToQStringList(lireListeChaines());
            emit activitesRecues(QlisteAct);
        }
        break;
    case ETUD_CHOIX_ACTIVITE_ :
        {
            string nick = lireChaine();
            string salle = lireChaine();
            string actid = lireChaine();
            QString qs = QString::fromStdString(nick);
            emit etudiants_recus(qs);
            emit message_act(QString::fromStdString(nick) + " s'est connecté à l'activité " + QString::fromStdString(actid));
            break;
        }
    case ETUD_OBS_REP_QCM:
        {
            string nick = lireChaine();
            string question = lireChaine();
            list<string> reponses = lireListeChaines();
            QString listereponses;
            int nbReponses = reponses.size();
            for(int i = 0 ; i< nbReponses; ++i)
            {
                listereponses.append(QString::fromStdString(reponses.front()) + "\n");
                reponses.pop_front();
            }
            emit message_act(QString::fromStdString(nick) + "a repondu a une question QCM.\nQuestion : " + QString::fromStdString(question)+ ".\nReponses : \n"+ listereponses+ "-----------------------------------------------");
            break;
        }
    case AST_OK_LOGIN :
        {
            ptrFenetre->activerAssistant();
            break;
        }
    case ETU_MSG :
        {
            string message = lireChaine();
            ptrFenetre->ecrireMessageChat(QString::fromStdString(message));
            break;
        }
    }
}

bool ObservateurBase::getConnecte()
{
    return connecte;
}

const char *ObservateurBase::getPort()
{
    return port;
}

const char *ObservateurBase::getIp()
{
    return ip;
}
string ObservateurBase::getNick()
{
    return login;
}

pthread_t ObservateurBase::getThreadLecture()
{
    return threadLecture;
}

